from datetime import datetime, timedelta
import os
from time import sleep

import selenium.webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions

import models
from floodorama import db


os.environ.setdefault("SELENIUM_SERVER_JAR", "C:\python34\selenium-server-standalone-2.43.1.jar")
MONTHS = ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября",
          "декабря"]


class ParsedDateTime:
    def __init__(self, year, month, day, hour, minite, likecount):
        self.year = year
        self.month = month
        self.day = day
        self.hour = hour
        self.minite = minite
        self.likes = likecount
        if self.day != -1:
            dt = datetime(year, month, day)
            self.weekday = dt.isoweekday()
        else:
            self.weekday = 0


def parse_dt(dtstring:str):
    try:
        cur_dt = datetime.now()
        dtstring = [q.lower() for q in dtstring.split()]
        likecount = 0
        if dtstring[-1] == '2013':
            return ParsedDateTime(2013, MONTHS.index(dtstring[1]) + 1, int(dtstring[0]), -1, -1, 0)
        elif dtstring[-1].isnumeric():
            likecount = int(dtstring.pop())
        if dtstring[-1] == '2013':
            return ParsedDateTime(2013, MONTHS.index(dtstring[1]) + 1, int(dtstring[0]), -1, -1, likecount)
        if "секунд" == dtstring[1]:
            return ParsedDateTime(2014, cur_dt.month, cur_dt.day, cur_dt.hour, cur_dt.minute, likecount)
        # print(ord(dtstring[1][0]))

        if dtstring[1].startswith("минут"):
            cur_dt -= timedelta(minutes=int(dtstring[0]))
            return ParsedDateTime(2014, cur_dt.month, cur_dt.day, cur_dt.hour, cur_dt.minute, likecount)
        time = dtstring[-1].split(":")
        if dtstring[0] in ["сегодня", "вчера"]:
            if dtstring[0][0] != "с":
                cur_dt -= timedelta(days=1)
            return ParsedDateTime(2014, cur_dt.month, cur_dt.day, int(time[0]), int(time[1]), likecount)
        return ParsedDateTime(2014, MONTHS.index(dtstring[1]) + 1, int(dtstring[0]), int(time[0]), int(time[1]),
                              likecount)
    except:
        return ParsedDateTime(-1, -1, -1, -1, -1, 0)


os.system("taskkill /f /im chromedriver.exe")
os.system("taskkill /f /im phantomjs.exe")
ops = ChromeOptions()
ops.add_argument("--disable-images")
ops.add_argument("--disable-bundled-ppapi-flash")

driver = selenium.webdriver.Chrome(chrome_options=ops)
driver2 = selenium.webdriver.PhantomJS()
sleep(2)


def parse_message(driver, url, msgid):
    driver.get(url)
    if not waitforload(2):
        return False
    if len(driver.page_source) < 600:
        return True
    # do not parse public messages
    if len(driver.find_elements_by_css_selector("div.MessageToMember.small")) != 0:
        return True  # success
    # who is sender of message, some kind of ***
    try:
        a1 = driver.find_elements_by_css_selector("td.tleft.small_light")[0]
    except:
        return False
    a2 = a1.find_element_by_class_name("input_3").get_attribute("value")
    sender = int(a2.split("&")[1][3:])
    # main post
    message_text = driver.find_element_by_class_name("MessageText").text
    msg_datetime_and_likes = parse_dt(driver.find_element_by_css_selector("div.MessageButtons.small_light").text)

    # comment_count = 0
    #if len(driver.find_elements_by_class_name("MessageCommentsCount")) != 0:
    #    comment_count = int(driver.find_element_by_class_name("MessageCommentsCount").text.split()[0])
    #parsing comments
    #first - view them all! require many time (((
    a = 20
    while True:
        links = driver.find_elements_by_partial_link_text("Показать")
        if len(links) == 0: break
        for k in links:
            if k.is_displayed():
                k.click()
                if not waitforload(0.7):
                    return False
                a += 20
                print('---->', a)
    comments = driver.find_elements_by_class_name("Message")[1:]
    # DB
    # if user is not in db, add
    main_user = db.session.query(models.User).filter_by(ffid=sender).first()
    if main_user is None:
        uname = get_username(driver2, "http://www.fanfics.me/index.php?section=profile&id=" + str(sender))
        main_user = models.User(ffid=sender, name=uname)
        db.session.add(main_user)
        db.session.add(models.Timedata(ffid=sender))
    #updating main table
    main_user = db.session.query(models.User).filter_by(ffid=sender).first()
    main_user.post_count += 1
    main_user.post_length += len(message_text)
    main_user.likecount += msg_datetime_and_likes.likes
    #updating date-time, some dirty-hacks
    DTRecord = db.session.query(models.Timedata).filter_by(ffid=main_user.ffid).first()
    DTRecord.inc("hour%d" % msg_datetime_and_likes.hour, 1)
    weekday = msg_datetime_and_likes.weekday
    if weekday != 0:
        DTRecord.inc("weekday%d" % weekday, 1)
    DTRecord.inc("month%d" % msg_datetime_and_likes.month, 1)
    #updating comments
    for k in comments:
        comm_sender_name = k.find_element_by_class_name("MessageRightUser").text
        comm_text = k.find_element_by_class_name("MessageText").text
        comm_time = parse_dt(k.find_element_by_css_selector("div.MessageButtons.small_light").text)
        # comm_sender_id
        tmp1 = k.find_element_by_class_name("MessageRightUser").find_element_by_css_selector("a")
        uid = int(tmp1.get_attribute("href").split("=")[-1])
        comm_user = db.session.query(models.User).filter_by(ffid=uid).first()
        if comm_user is None:
            comm_user = models.User(ffid=uid, name=comm_sender_name)
            db.session.add(comm_user)
            DTRecord2 = models.Timedata(ffid=uid)
            db.session.add(DTRecord2)
        comm_user = db.session.query(models.User).filter_by(ffid=uid).first()
        DTRecord2 = db.session.query(models.Timedata).filter_by(ffid=uid).first()
        comm_user.comment_count += 1
        comm_user.comment_length += len(comm_text)
        DTRecord2.inc("hour%d" % comm_time.hour, 1)
        weekday = comm_time.weekday
        if weekday != 0:
            DTRecord2.inc("weekday%d" % weekday, 1)
        DTRecord2.inc("month%d" % comm_time.month, 1)
        # upd common, the difficult part
        common_row = db.session.query(models.JoinedData).filter_by(first=uid, second=sender).first()
        if common_row is None:
            common_row = models.JoinedData(first=uid, second=sender)
            db.session.add(common_row)
        common_row = db.session.query(models.JoinedData).filter_by(first=uid, second=sender).first()
        common_row.comment_count += 1
        common_row.comment_len += len(comm_text)
    #TODO if except, return false
    db.session.commit()
    # write source code
    try:
        ff = open("msg_%d_%d.html" % (msgid, sender), "w", encoding="utf16")
        print(driver.page_source, file=ff)
        ff.close()
    except:
        pass

    return True


def get_username(driver, url):
    # TODO optimize
    # id <-> ffname
    driver.get(url)
    if not waitforload(1):
        print("Argh!")
        input()
    if len(driver.page_source) < 600:
        return -1
    uname = ' '.join(driver.title.split()[1:])
    return uname


def waitforload(ts):
    cnt = 0
    while driver.execute_script("return document.readyState") != "complete":
        sleep(0.4)
        cnt += 1
        if cnt > 42:
            return False
    sleep(ts)
    return True


for i in range(7, 100000):
    print(i)
    parse_message(driver, "http://www.fanfics.me/index.php?section=profile&id=1&message_id=%d" % i, i)
